import {
  FormilySchema,
  JsonSchema,
  ComponentInfo,
  GenerateOptions,
} from './types.js'
import fs from 'fs-extra'
import path from 'path'
import { demoSchemas } from './demo-schemas.js'

export class SchemaGenerator {
  constructor() {
    // 不再需要项目路径，只使用demo-schemas数据
  }

  /**
   * 获取所有演示Schema数据
   */
  async scanSchemas(): Promise<ComponentInfo[]> {
    const components: ComponentInfo[] = []

    // 直接使用演示数据
    for (const [componentName, schema] of Object.entries(demoSchemas)) {
      components.push({
        name: componentName,
        path: `demo/${componentName}.ts`,
        schema: schema,
        category: 'demo',
        description: this.extractDescription(schema),
      })
    }

    return components
  }

  /**
   * 将Formily Schema转换为标准JSON Schema
   */
  convertToJsonSchema(
    formilySchema: FormilySchema,
    options: GenerateOptions = {}
  ): JsonSchema {
    const jsonSchema: JsonSchema = {
      $schema: 'http://json-schema.org/draft-07/schema#',
      type: formilySchema.type || 'object',
    }

    if (formilySchema.properties) {
      jsonSchema.properties = {}

      for (const [key, prop] of Object.entries(formilySchema.properties)) {
        jsonSchema.properties[key] = this.convertProperty(prop, options)
      }
    }

    if (formilySchema.required) {
      jsonSchema.required = Array.isArray(formilySchema.required)
        ? formilySchema.required
        : []
    }

    if (formilySchema.items) {
      jsonSchema.items = this.convertProperty(formilySchema.items, options)
    }

    if (formilySchema.enum) {
      jsonSchema.enum = formilySchema.enum
    }

    if (formilySchema.description) {
      jsonSchema.description = formilySchema.description
    }

    if (formilySchema.title) {
      jsonSchema.title = formilySchema.title
    }

    return jsonSchema
  }

  /**
   * 转换单个属性
   */
  private convertProperty(prop: FormilySchema, options: GenerateOptions): any {
    const converted: any = {
      type: prop.type,
    }

    if (prop.enum) {
      converted.enum = prop.enum
    }

    if (prop.description) {
      converted.description = prop.description
    }

    if (prop.title) {
      converted.title = prop.title
    }

    if (prop.default !== undefined) {
      converted.default = prop.default
    }

    if (prop.properties) {
      converted.properties = {}
      for (const [key, subProp] of Object.entries(prop.properties)) {
        converted.properties[key] = this.convertProperty(subProp, options)
      }
    }

    if (prop.items) {
      converted.items = this.convertProperty(prop.items, options)
    }

    // 包含Formily特定属性
    if (options.includeFormilyProps) {
      if (prop['x-decorator']) {
        converted['x-decorator'] = prop['x-decorator']
      }
      if (prop['x-component']) {
        converted['x-component'] = prop['x-component']
      }
      if (prop['x-component-props']) {
        converted['x-component-props'] = prop['x-component-props']
      }
    }

    // 包含验证规则
    if (options.includeValidation && prop['x-validator']) {
      converted['x-validator'] = prop['x-validator']
    }

    // 包含响应式规则
    if (options.includeReactions && prop['x-reactions']) {
      converted['x-reactions'] = prop['x-reactions']
    }

    return converted
  }

  /**
   * 生成所有组件的JSON Schema
   */
  async generateAllSchemas(
    options: GenerateOptions = {}
  ): Promise<Record<string, JsonSchema>> {
    const components = await this.scanSchemas()
    const schemas: Record<string, JsonSchema> = {}

    for (const component of components) {
      try {
        const jsonSchema = this.convertToJsonSchema(component.schema, options)
        schemas[component.name] = jsonSchema
      } catch (error) {
        console.error(`生成组件 ${component.name} 的Schema时出错:`, error)
      }
    }

    return schemas
  }

  /**
   * 保存Schema到文件
   */
  async saveSchemas(
    schemas: Record<string, JsonSchema>,
    outputPath: string,
    options: GenerateOptions = {}
  ): Promise<void> {
    await fs.ensureDir(path.dirname(outputPath))

    if (options.outputFormat === 'yaml') {
      // 这里可以添加YAML支持
      throw new Error('YAML格式暂未实现')
    } else {
      await fs.writeJSON(outputPath, schemas, { spaces: 2 })
    }
  }

  /**
   * 从Schema中提取描述
   */
  private extractDescription(schema: any): string {
    if (schema.description) {
      return schema.description
    }
    if (schema.title) {
      return schema.title
    }
    return ''
  }

  /**
   * 分析组件依赖关系
   */
  async analyzeDependencies(): Promise<Record<string, string[]>> {
    const components = await this.scanSchemas()
    const dependencies: Record<string, string[]> = {}

    for (const component of components) {
      dependencies[component.name] = this.extractDependencies(component.schema)
    }

    return dependencies
  }

  /**
   * 从Schema中提取依赖的组件
   */
  private extractDependencies(schema: FormilySchema): string[] {
    const deps = new Set<string>()

    const traverse = (obj: any) => {
      if (typeof obj !== 'object' || obj === null) return

      if (obj['x-component']) {
        deps.add(obj['x-component'])
      }

      if (obj['x-decorator']) {
        deps.add(obj['x-decorator'])
      }

      if (obj.properties) {
        Object.values(obj.properties).forEach(traverse)
      }

      if (obj.items) {
        traverse(obj.items)
      }
    }

    traverse(schema)
    return Array.from(deps)
  }
}
